PORTFOLIO Web-Programmierung • Lerntagebuch & Arbeitsproben
🔍
Portfolioprüfung WiSe 2026/27 Status: Alle Übungen V1–V5 abgeschlossen

Studien-Portfolio & Lerntagebuch: Web-Programmierung

Studienbegleitendes Portfolio im Modul „Entwicklung verteilter Systeme“ bei Prof. Dr. Stefan Noll. Diese Webseite dokumentiert alle praktischen Programmierübungen (mit Live-Ausführung und Lernreflexion), das chronologische Lerntagebuch der Vorlesungen sowie das ausgearbeitete Schwerpunktthema.

📌 Portfolio-Steckbrief (klickbar zum Anpassen)
Verfasser: Jamil
Modul: Entwicklung verteilter Systeme
Veranstaltung: Web-Programmierung (WiSe 26)
Dozent: Prof. Dr. Stefan Noll
Prüfungsform: Portfolioprüfung (Tagebuch + Übungen + Schwerpunkt)

Meine Programmierübungen & Pflichtabgaben (Live-Demos & Reflexion)

🫘 Pflichtübung V3: Bohnen zählen ✓ Abgabe erledigt

Aufgabe (V3, Folie 35): Implementierung von countBs(string) und countChar(string, zeichen) mithilfe von ES6-Pfeilfunktionen (=>).

💡 Meine Lernreflexion & Lösungsansatz: Durch die Verallgemeinerung in countChar(string, zeichen) konnte ich Code-Duplizierung vermeiden (DRY-Prinzip). countBs wurde als einzeilige Arrow-Funktion mit implizitem Return umgesetzt: const countBs = (string) => countChar(string, "B");.
bohnen.html öffnen ↗
1. countBs(string) & 2. countChar(string, zeichen)
// Funktion countChar mit Pfeilfunktion
const countChar = (string, zeichen) => {
    let anzahl = 0;
    for (let i = 0; i < string.length; i++) {
        if (string[i] === zeichen) {
            anzahl++;
        }
    }
    return anzahl;
};

// Funktion countBs mit Pfeilfunktion (nutzt countChar)
const countBs = (string) => countChar(string, "B");

💶 Pflichtübung V4: Währungsumrechner ✓ Abgabe erledigt

Aufgabe (V4, Folie 53): Formularbasierter Umrechner zwischen 2 Währungen ($ und €) mit Radio-Buttons und Komma-Notation (replace).

💡 Meine Lernreflexion & Lösungsansatz: Da parseFloat() in JavaScript einen Dezimalpunkt erwartet, wandle ich die deutsche Komma-Eingabe zuerst per eingabeText.replace(",", ".") um, prüfe mit isNaN() auf Fehleingaben und formatiere das Ergebnis mit toFixed(2).replace(".", ",") zurück.
Währungsrechner.html ↗
Währungsumrechner (1 € = 1,12 $)
function umrechnen() {
    let eingabeText = document.getElementById("eingabe").value.trim();
    let eingabeMitPunkt = eingabeText.replace(",", ".");
    let betrag = parseFloat(eingabeMitPunkt);
    if (isNaN(betrag)) { alert("Bitte gültigen Betrag eingeben."); return; }

    const KURS_DOLLAR = 1.12;
    let richtung = document.querySelector('input[name="richtung"]:checked').value;
    let ergebnis = (richtung === "dollarZuEuro") ? (betrag / KURS_DOLLAR) : (betrag * KURS_DOLLAR);
    document.getElementById("ausgabe").value = ergebnis.toFixed(2).replace(".", ",");
}

📐 Pflichtübung V2: *-Dreieck ✓ Abgabe erledigt

Aufgabe (V2, Folie 59): Ausgabe eines *-Dreiecks in HTML und auf der Konsole mithilfe geschachtelter Schleifen nach Benutzereingabe der Zeilenanzahl.

💡 Meine Lernreflexion & Lösungsansatz: Weil prompt() immer einen String zurückliefert, wende ich parseInt(..., 10) an. Die äußere Schleife (i = 1..zeilen) steuert die Zeilen, während die innere Schleife (j = 1..i) pro Zeile genau i Sterne verkettet.
dreieck.html öffnen ↗
Geschachtelte for-Schleifen
let zeilen = parseInt(prompt("Bitte geben Sie die Anzahl der Zeilen ein:"), 10);

for (let i = 1; i <= zeilen; i++) {
    let sternZeile = "";
    for (let j = 1; j <= i; j++) {
        sternZeile += "*";
    }
    console.log(sternZeile);
    document.write(sternZeile + "<br>");
}

📇 Pflichtübung V5: Klasse Kontakte ✓ Abgabe erledigt

Aufgabe (V5, Folie 65): ES2022-Klasse mit privaten Eigenschaften (#), static gesamtZahl, get/set-Methoden und checkUser().

💡 Meine Lernreflexion & Lösungsansatz: Durch die ES2022 #-Syntax sind Felder wie #vorname und #laufendeNummer echt gekapselt: Ein Direktzugriff von außen führt zu einem SyntaxError. Die statische Variable Kontakte.gesamtZahl wird im Konstruktor bei jeder Instanziierung hochgezählt.
kontakte.html öffnen ↗
Kontakt anlegen & Kapselung testen
class Kontakte {
    static gesamtZahl = 0;
    #laufendeNummer; #vorname; #nachname; #telMobil; #email; #wohnort;

    constructor(vorname, nachname, telMobil, email, wohnort) {
        Kontakte.gesamtZahl++;
        this.#laufendeNummer = Kontakte.gesamtZahl;
        this.#vorname = vorname;
        this.#nachname = nachname;
        this.#telMobil = telMobil;
        this.#email = email;
        this.#wohnort = wohnort;
    }
    // get + set für ALLE privaten Instanzvariablen
    get laufendeNummer() { return this.#laufendeNummer; }
    set laufendeNummer(nr) { this.#laufendeNummer = Number(nr); }
    get vorname() { return this.#vorname; }
    set vorname(v) { this.#vorname = v; }
    get nachname() { return this.#nachname; }
    set nachname(n) { this.#nachname = n; }
    get telMobil() { return this.#telMobil; }
    set telMobil(t) { this.#telMobil = t; }
    get email() { return this.#email; }
    set email(e) { this.#email = e; }
    get wohnort() { return this.#wohnort; }
    set wohnort(w) { this.#wohnort = w; }

    checkUser(v, n) { return this.#vorname === v && this.#nachname === n; }
    getKontaktDaten() { return `#${this.#laufendeNummer}: ${this.#vorname} ${this.#nachname} (${this.#telMobil}, ${this.#email}, ${this.#wohnort})`; }
}

☕ HTML-Übung 1: Sternback-Kaffee ✓ Erledigt

Aufgabe (HTML Teil 1): Umsetzung der Sternback-Getränkekarte mit semantischen Überschriften, Absätzen und individuellem CSS-Design.

💡 Meine Lernreflexion & Gestaltung: Neben der Grundstruktur aus der Vorlesung (<h1>, <h2>, <p>) habe ich das Layout in sternback.html mit einem modernen Farbverlauf (linear-gradient), abgerundeten Ecken (border-radius), box-shadow und hervorgehobenen Preisen (<strong>) erweitert.
sternback.html ↗
sternback.html – Willkommen bei Sternback Kaffee

Getränke bei Sternback-Kaffee

Hausmischung, € 1.49

Eine feine, milde Mischung verschiedener Kaffeesorten aus Mexiko, Bolivien und Guatemala.

Mokka Café Latte, € 2.35

Espresso, heiße Milch und Schokosirup.

Cappuccino, € 1.89

Eine Mischung aus Espresso, heißer Milch und Milchschaum.

Chai-Tee, € 1.85

Eine würzige Mélange aus schwarzem Tee, Gewürzen, Milch und Honig.

<h1>Getränke bei <br>Sternback-Kaffee</h1>
<h2>Hausmischung, <strong style="color: black;">€ 1.49</strong></h2>
<p>Eine feine, milde Mischung verschiedener Kaffeesorten aus Mexiko, Bolivien und Guatemala.</p>

🖱️ Übungen V1 & V2: Events, Dialoge & Zahlenraten ✓ Erledigt

Aufgaben: Event-Handling mit onclick (test1.html), Benutzereingabe via prompt() (event.html) und das Zahlenraten-Spiel (V2).

💡 Meine Lernreflexion: Beim Verschachteln von Strings im HTML-Attribut onclick="alert('Hello')" müssen innen einfache Anführungszeichen stehen. Beim Zahlenraten-Spiel nutzt JS automatische Typkonvertierung (Type Coercion) beim Vergleich des prompt()-Strings mit der Zufallszahl.
test1.html ↗ event.html ↗
test1.html, event.html & Zahlenraten (1–100)
Teste die Dialog-Buttons oder gib eine Zahl zwischen 1 und 100 für das Zahlenraten-Spiel ein!
<!-- test1.html -->
<input type="button" value="Drücke mich" onclick="alert('Hello')">

<!-- event.html -->
<script>alert("Sie sind " + prompt("Wie alt sind Sie? ") + " Jahre alt");</script>

Vertiefungsthema: Objektorientierung, Kapselung & this-Kontext in modernem JavaScript

⭐ Ausarbeitung für die Portfolio-Präsentation (5–10 Minuten)

Gemäß den Vorgaben zur Portfolioprüfung (Vorlesung 1, Folie 14) vertieft dieser Schwerpunkt die Entwicklung der Objektorientierung in JavaScript – von klassischen Konstruktorfunktionen und Closure-Kapselung bis hin zu modernen ES6-Klassen, ES2022 Private Fields (#) und der Lösung des this-Kontextverlusts bei Callbacks/Events.

1. Vergleich: Kapselung über Closures vs. ES2022 #-Felder

Kriterium Closure im Konstruktor (Vor ES2022) ES2022 Private Fields (#prop)
Syntax Lokale Variable let _name = name; im Konstruktor Deklaration #name; direkt im class-Körper
Zugriff von außen obj._name liefert undefined (legt bei Zuweisung versehentlich neue Public-Property an!) Wird bereits vom JS-Parser blockiert: wirft sofort SyntaxError!
Speicherverbrauch Jede privilegierte Methode muss pro Instanz neu im Konstruktor erzeugt werden. Methoden liegen effizient auf dem Prototyp und können trotzdem auf this.#name zugreifen!

2. Warum geht this in Event-Handlern & Callbacks verloren?

In Java ist this fest an die Instanz gebunden. In JavaScript hängt this allein vom Aufrufkontext zur Laufzeit ab:

class Zaehler {
  #wert = 0;
  // Problem: Klassische Methode verliert 'this', wenn sie als Callback übergeben wird!
  erhoehenKlassisch() { this.#wert++; }

  // Lösung A: Arrow-Property (bindet 'this' lexikalisch an die Instanz)
  erhoehenSicher = () => { this.#wert++; return this.#wert; };
}

Vorlesung 1: Web-Anwendungen, Architekturen & Skriptsprachen

🌐 Client-Server & 3 Software-Architekturen

  1. Rein client-seitig (Rich Client): Server liefert HTML + Programm (z.B. neueAnw.jar via Java Web Start).
  2. Rein server-seitig: Server führt Skripte/Programme aus (PHP, Java Servlets, JSP, CGI), fragt Datenbank ab und schickt fertiges HTML an den Browser.
  3. Moderne Hybrid-Architektur (Client + Server):
    • Client-seitig (JS + DOM): Dokumentänderung direkt im Browser (Plausibilitäts-Checks, Formularanpassung, lokale Dialoge, Animationen, asynchrone Interaktivität wie Autocomplete).
    • Server-seitig: Datenbankanbindung & Geschäftslogik. (Wichtig: Java ≠ JavaScript!).

⚙️ Compiler vs. Interpreter & Erste JS-Regeln

  • Compiler (z.B. Java, C++): Übersetzt komplett vorab; statische Semantik prüft Typ- und Bindungsregeln vor der Ausführung.
  • Interpreter (z.B. JavaScript, PHP): Führt Code direkt aus; Bindungs- und Typregeln werden erst zur Laufzeit geprüft (nicht ausgeführte Zweige bleiben ungeprüft!).
  • Erste JS-Grundregeln:
    • alert(17 + 5 * 3) berechnet 32; in Anführungszeichen alert("17 + 5 * 3") wird es als Text ausgegeben.
    • In HTML-Attributen wie onclick="alert('Hallo!')" müssen einfache und doppelte Anführungszeichen abgewechselt werden.
    • <noscript> wird nur angezeigt, wenn JavaScript im Browser deaktiviert ist.

📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 1 (wird lokal gespeichert):

Vorlesung 2: Konsole, Dynamische Typisierung, Scope, Arrays & Operatoren

📦 Dynamische Typisierung, let / const / var & Scope

  • Dynamische Typisierung: Variablen haben keinen festen Typ bei der Deklaration; JS kennt nur number für Ganz- und Fließkommazahlen.
  • let & const (ab ES6): Haben Block-Scope ({ ... }). var hat nur Funktions-Scope.
  • Kritische Fehlerquelle: Lässt man let/const/var bei einer Zuweisung in einer Funktion weg (z.B. y = 17;), wird y automatisch als globale Variable angelegt! "use strict"; am Skriptanfang verhindert dies.
  • undefined vs. null: Nicht initialisierte Variablen/fehlende Parameter sind automatisch undefined; null weist man explizit als „leeren Wert“ zu.
Live-Demo: DOM-Manipulation (Folien 6–9)

Ursprünglicher Text

📚 Array-Methoden, Template-Literale & Operatoren

  • Template-Literale (Backticks): `Die Hälfte von 100 ist ${100 / 2}` (erlaubt Zeilenumbrüche und Berechnungen).
  • Strikte Gleichheit: === und !== prüfen Wert und Datentyp (keine implizite Typumwandlung wie bei ==).
  • Die 14 Array-Methoden (Folie 41):
    • Ende: push() (anfügen), pop() (entfernen)
    • Anfang: unshift() (einfügen), shift() (entfernen)
    • Teile & Umbau: slice(), splice(), concat(), join(), reverse(), sort()
    • Funktional: forEach(), map(), filter(), reduce()

📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 2:

Vorlesung 3: First-Class Functions, Arrow-Syntax, Rest/Spread & Pure Functions

🥇 4 Arten der Funktionserzeugung & Arrow-Kurzformen

  1. Funktionsanweisung: function add(a, b) { return a + b; }
  2. Funktionsausdruck: const add = function(a, b) { return a + b; };
  3. Function-Konstruktor
  4. Pfeilfunktion (Arrow Function =>):
    • Einzelner Return-Ausdruck ➔ { } und return weglassen: (a, b) => a + b
    • Genau 1 Parameter ➔ ( ) weglassen: x => x * x
    • 0 Parameter ➔ leere Klammern () sind Pflicht: () => "Hallo"

🔄 Rest-Parameter, Spread-Operator & Pure Functions

  • Rest-Parameter (...numbers): Sammelt beliebig viele übergebene Argumente in einem echten Array (im Gegensatz zum alten, nur array-ähnlichen arguments-Objekt).
  • Spread-Operator (...): Entpackt Elemente eines Arrays/Objekts. Wichtigste Anwendung: Flache Kopie erzeugen (let copy = { ...orig };), um das Copy-by-Reference-Problem zu lösen!
  • Pure Function (Reine Funktion): Hängt nur von ihren Parametern ab, verändert keine externen Variablen oder übergebenen Objekte (Immutability per Spread: const buyCar = p => ({ ...p, hasCar: true });).
  • Higher-Order Functions & Closures: Funktionen, die Funktionen als Parameter erhalten oder als Ergebnis zurückgeben (z.B. multiplier(factor)).

📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 3:

Vorlesung 4: Das String-Objekt & Formulare im DOM

🧵 String-Methoden & Live-Tester (0-basiert)

  • .length: Eigenschaft (keine Klammern ()!), schreibgeschützt.
  • .charAt(index): Zeichen an Position index (0-basiert).
  • .indexOf(such [, start]) / .lastIndexOf(such [, start]): Sucht vorwärts bzw. rückwärts; gibt -1 zurück, wenn nicht gefunden.
  • .substring(anfang, ende): Kopiert von anfang (inklusive) bis ende (exklusive!).
  • .split(trennzeichen): Zerlegt String in ein Array von Teilstrings.
Live String-Tester

📋 Formular-Adressierung & die 10 Formular-Objekte

  • 3 Zugriffswege im DOM:
    1. Über Arrays: document.forms[0].elements[0]
    2. Über Namen: document.meinFormular.eingabe1
    3. Über W3C-DOM: document.getElementById("eingabe1") (oder relativ im Event über this.form.eingabe1)
  • Besonderheiten der Formular-Elemente:
    • textarea: Attribut wrap="off | virtual | physical".
    • password: Nur optisch maskiert – in JS .value und beim unverschlüsselten Versand im Klartext!
    • checkbox & radio: Status über .checked. Bei Radiogruppen per Schleife über das Array iterieren!
    • select: Einfachauswahl über selectedIndex; Mehrfachauswahl (multiple) per Schleife über liste[i].selected. Neue Option: liste[liste.length] = new Option("Neu");, Löschen: liste[2] = null;.

📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 4:

Vorlesung 5: Objekte, JSON, ES6-Klassen, Kapselung & Destructuring

🧱 4 Wege der Objekterzeugung & JSON-Regeln

  1. new Object() (allgemeiner Konstruktor)
  2. Objekt-Literal { name: "Fred", ... } (Einzelinstanz)
  3. Konstruktorfunktion function Person(name) { this.name = name; } mit new
  4. ES6-Klassen class Person { constructor(name) { ... } } (bei extends muss im Subklassen-Konstruktor zuerst super() gerufen werden!)

Strenge Regeln für JSON (JavaScript Object Notation):

  • Alle Eigenschaftsnamen müssen in doppelten Anführungszeichen "..." stehen!
  • Keine Methoden/Funktionen, keine Berechnungen, keine Kommentare!
  • Methoden: JSON.stringify(obj) (Objekt ➔ Text) und JSON.parse(text) (Text ➔ Objekt).

🧩 Destructuring & Object Literal Enhancement

// Array- & Objekt-Destructuring
let [a, b, ...rest] = [44, 67, 90, 56];
const hero = { name: 'Batman', realName: 'Bruce Wayne' };
const { name, realName } = hero;

// Wichtig: Bei bereits deklarierter Variable runde Klammern um die Zuweisung!
let n;
({ name: n } = hero);

// Gegenstück: Object Literal Enhancement
let gipfel = "Zugspitze", hoehe = 2962;
let berg = { gipfel, hoehe };

📝 Meine persönlichen Lerntagebuch-Notizen zu Vorlesung 5:

HTML & CSS Teil 1 bis 5 („Von Kopf bis Fuß“)

📙 HTML 1 & 2: Grundstruktur, Attribute & Relative Pfade

  • Anatomie: Element = Start-Tag + Inhalt + End-Tag. Mehrfache Leerzeichen/Umbrüche (Whitespace) im Quellcode werden vom Browser ignoriert.
  • Attribute: Immer name="wert" in doppelten Anführungszeichen (z.B. <a href="ziel.html">).
  • Relative Pfade:
    • Unterordner: href="getraenke/elixir.html"
    • Elternordner (eine Ebene höher): href="../bar.html" (zwei Ebenen: ../../)
    • Pfadtrenner im Web ist immer / (Forward-Slash)!

📙 HTML 3: Block vs. Inline, Zitate, Listen & Entities

  • Block-Elemente (eigener Umbruch): <h1>–<h6>, <p>, <blockquote>, <ol>, <ul>, <li>.
  • Inline-Elemente (im Textfluss): <q>, <a>, <em>, <strong>, <img>, <code>.
  • Inhaltsleere Elemente (Void): <br>, <img>, <link>, <meta>.
  • Listen: <ol> (nummeriert) und <ul> (Punkte) dürfen direkt nur <li> enthalten! Definitionsliste: <dl> mit <dt> und <dd>.
  • Entities: &gt; (>), &lt; (<), &amp; (&), &auml;, &ouml;, &uuml;, &szlig;.

📙 HTML 4 & 5: CSS-Regeln, Externe Stylesheets, Vererbung & Spezifität

  • CSS-Regel: Selektor { eigenschaft: wert; } (Gruppierung mit Komma: h1, h2 { ... }).
  • Externes Stylesheet: <link type="text/css" rel="stylesheet" href="bar.css"> im <head>. In der .css-Datei dürfen keine <style>-Tags stehen!
  • Vererbung: Text-Eigenschaften (color, font-family) werden im DOM-Baum vererbt; Rahmen/Box-Eigenschaften (border) nicht.
  • Klassen & Konfliktlösung (Kaskade):
    1. Spezifität gewinnt: p.gruenertee schlägt .gruenertee, und .gruenertee schlägt p.
    2. Bei gleicher Spezifität: Es gewinnt die Regel, die in der CSS-Datei am weitesten unten (zuletzt) steht! Die Reihenfolge in class="a b c" im HTML ist egal.

Interaktiver Kurztest- & Prüfungstrainer (Vorlesung 1 bis 5 & HTML/CSS)

🎯 Wissens-Check für den 20-Punkte-Kurztest & die mündliche Portfolioprüfung

Beantworte die folgenden typischen Prüfungsfragen aus den Vorlesungsskripten von Prof. Dr. Noll: